import React, { useRef, useEffect, useState, useCallback } from 'react';

// 定义接口
interface Point {
  x: number;
  y: number;
  color?: string;
  label?: string;
  radius?: number;
}

interface Line {
  points: { x: number; y: number }[];
  color?: string;
  width?: number;
}

interface CoordinateChartProps {
  width?: number;
  height?: number;
  points?: Point[];
  lines?: Line[];
  horizontalTrend?: number | null;
  scale?: number;
  showGrid?: boolean;
  gridColor?: string;
  axisColor?: string;
  autoResize?: boolean; // 新增：是否自适应父容器
  aspectRatio?: number; // 新增：宽高比，默认4:3
}

interface CanvasPoint {
  x: number;
  y: number;
}

const CoordinateChart: React.FC<CoordinateChartProps> = ({
  width: propWidth,
  height: propHeight,
  points = [],
  lines = [],
  horizontalTrend = null,
  scale = 4,
  showGrid = true,
  gridColor = '#f0f0f0',
  axisColor = '#333',
  autoResize = true,
  aspectRatio = 4/3
}) => {
  const containerRef = useRef<HTMLDivElement>(null);
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const [dimensions, setDimensions] = useState({ width: propWidth || 225, height: propHeight || 169 });

  // 响应式尺寸计算
  const updateDimensions = useCallback(() => {
    if (!autoResize || !containerRef.current) return;

    const container = containerRef.current;
    const containerWidth = container.clientWidth; // 移除padding减值
    const containerHeight = container.clientHeight;

    let newWidth: number;
    let newHeight: number;

    if (propWidth && propHeight) {
      // 如果指定了固定尺寸，使用固定尺寸
      newWidth = propWidth;
      newHeight = propHeight;
    } else if (containerWidth / containerHeight > aspectRatio) {
      // 容器更宽，以高度为准
      newHeight = Math.max(containerHeight, 112); // 最小高度112
      newWidth = newHeight * aspectRatio;
    } else {
      // 容器更高，以宽度为准
      newWidth = Math.max(containerWidth, 150); // 最小宽度150
      newHeight = newWidth / aspectRatio;
    }

    setDimensions({ width: newWidth, height: newHeight });
  }, [autoResize, propWidth, propHeight, aspectRatio]);

  // 监听容器尺寸变化
  useEffect(() => {
    updateDimensions();

    if (!autoResize) return;

    const resizeObserver = new ResizeObserver(() => {
      updateDimensions();
    });

    if (containerRef.current) {
      resizeObserver.observe(containerRef.current);
    }

    return () => {
      resizeObserver.disconnect();
    };
  }, [updateDimensions, autoResize]);

  const { width, height } = dimensions;

  // 坐标系设置 - 原点靠左下
  const centerX = width * 0.25; // 原点在左侧1/4处
  const centerY = height * 0.75; // 原点在下方3/4处

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;

    const ctx = canvas.getContext('2d');
    if (!ctx) return;

    const dpr = window.devicePixelRatio || 1;

    // 设置高DPI支持
    canvas.style.width = `${width}px`;
    canvas.style.height = `${height}px`;
    canvas.width = width * dpr;
    canvas.height = height * dpr;
    ctx.scale(dpr, dpr);

    drawChart(ctx);
  }, [points, lines, horizontalTrend, scale, showGrid, width, height, centerX, centerY]);

  const drawChart = (ctx: CanvasRenderingContext2D): void => {
    // 清除画布
    ctx.clearRect(0, 0, width, height);

    // 绘制网格
    if (showGrid) {
      drawGrid(ctx);
    }

    // 绘制坐标轴
    drawAxes(ctx);

    // 绘制线条
    lines.forEach((line, index) => {
      drawLine(ctx, line, index);
    });

    // 绘制点
    points.forEach(point => {
      drawPoint(ctx, point);
    });

    // 绘制水平趋势标签
    if (horizontalTrend !== null) {
      drawHorizontalTrendLabel(ctx);
    }

    // 绘制点标签
    points.forEach(point => {
      drawPointLabel(ctx, point);
    });
  };

  const drawGrid = (ctx: CanvasRenderingContext2D): void => {
    ctx.strokeStyle = gridColor;
    ctx.lineWidth = 0.3 * (width / 450); // 根据尺寸缩放线宽

    // 垂直网格线
    for (let i = -20; i <= 100; i += 10) {
      const x = centerX + i * scale;
      if (x > 50 && x < width - 50) {
        ctx.beginPath();
        ctx.moveTo(x, 50);
        ctx.lineTo(x, height - 50);
        ctx.stroke();
      }
    }

    // 水平网格线
    for (let i = -20; i <= 60; i += 10) {
      const y = centerY - i * scale;
      if (y > 50 && y < height - 50) {
        ctx.beginPath();
        ctx.moveTo(50, y);
        ctx.lineTo(width - 50, y);
        ctx.stroke();
      }
    }
  };

  const drawAxes = (ctx: CanvasRenderingContext2D): void => {
    const scaleFactor = width / 450; // 基于原始450px宽度的缩放因子
    ctx.strokeStyle = axisColor;
    ctx.lineWidth = 2 * scaleFactor;

    // X轴 - 短负轴，长正轴
    ctx.beginPath();
    ctx.moveTo(centerX - 100, centerY); // 负轴较短
    ctx.lineTo(width - 50, centerY); // 正轴较长
    ctx.stroke();

    // Y轴 - 短负轴，长正轴
    ctx.beginPath();
    ctx.moveTo(centerX, centerY + 100); // 负轴较短
    ctx.lineTo(centerX, 50); // 正轴较长
    ctx.stroke();

    // 绘制箭头 - 缩放箭头大小
    const arrowSize = 6 * scaleFactor;
    drawArrow(ctx, width - 50, centerY, width - 50 - 10 * scaleFactor, centerY - arrowSize);
    drawArrow(ctx, width - 50, centerY, width - 50 - 10 * scaleFactor, centerY + arrowSize);
    drawArrow(ctx, centerX, 50, centerX - arrowSize, 50 + 10 * scaleFactor);
    drawArrow(ctx, centerX, 50, centerX + arrowSize, 50 + 10 * scaleFactor);
  };

  const drawArrow = (ctx: CanvasRenderingContext2D, x: number, y: number, x2: number, y2: number): void => {
    const scaleFactor = width / 450;
    ctx.strokeStyle = axisColor;
    ctx.lineWidth = 2 * scaleFactor;
    ctx.beginPath();
    ctx.moveTo(x, y);
    ctx.lineTo(x2, y2);
    ctx.stroke();
  };

  const drawLine = (ctx: CanvasRenderingContext2D, line: Line, index: number): void => {
    const scaleFactor = width / 450;
    const { points: linePoints, color = ['#2196F3', '#FF5722'][index % 2], width: lineWidth = 4 } = line;

    if (linePoints.length < 2) return;

    ctx.strokeStyle = color;
    ctx.lineWidth = lineWidth * scaleFactor; // 缩放线宽

    ctx.beginPath();
    const startPoint = transformPoint(linePoints[0]);
    ctx.moveTo(startPoint.x, startPoint.y);

    for (let i = 1; i < linePoints.length; i++) {
      const point = transformPoint(linePoints[i]);
      ctx.lineTo(point.x, point.y);
    }
    ctx.stroke();

    // 绘制箭头（只在最后一段）
    if (linePoints.length >= 2) {
      const lastTwo = linePoints.slice(-2);
      const from = transformPoint(lastTwo[0]);
      const to = transformPoint(lastTwo[1]);
      drawLineArrow(ctx, from.x, from.y, to.x, to.y, color);
    }
  };

  const drawLineArrow = (ctx: CanvasRenderingContext2D, fromX: number, fromY: number, toX: number, toY: number, color: string): void => {
    const scaleFactor = width / 450;
    const dx = toX - fromX;
    const dy = toY - fromY;
    const angle = Math.atan2(dy, dx);

    const arrowLength = 15 * scaleFactor; // 缩放箭头长度
    const arrowAngle = Math.PI / 6;

    const arrowX1 = toX - arrowLength * Math.cos(angle - arrowAngle);
    const arrowY1 = toY - arrowLength * Math.sin(angle - arrowAngle);
    const arrowX2 = toX - arrowLength * Math.cos(angle + arrowAngle);
    const arrowY2 = toY - arrowLength * Math.sin(angle + arrowAngle);

    ctx.strokeStyle = color;
    ctx.fillStyle = color;
    ctx.lineWidth = 2 * scaleFactor; // 缩放箭头线宽

    ctx.beginPath();
    ctx.moveTo(toX, toY);
    ctx.lineTo(arrowX1, arrowY1);
    ctx.lineTo(arrowX2, arrowY2);
    ctx.closePath();
    ctx.fill();
    ctx.stroke();
  };

  const drawPoint = (ctx: CanvasRenderingContext2D, point: Point): void => {
    const scaleFactor = width / 450;
    const { x, y, color = '#2196F3', radius = 6 } = point;
    const canvasPoint = transformPoint({ x, y });
    const scaledRadius = radius * scaleFactor; // 缩放点的半径

    ctx.fillStyle = color;
    ctx.beginPath();
    ctx.arc(canvasPoint.x, canvasPoint.y, scaledRadius, 0, Math.PI * 2);
    ctx.fill();

    // 白色边框
    ctx.strokeStyle = 'white';
    ctx.lineWidth = 2 * scaleFactor; // 缩放边框宽度
    ctx.stroke();
  };

  const drawPointLabel = (ctx: CanvasRenderingContext2D, point: Point): void => {
    const scaleFactor = width / 450;
    const { x, y, label, color = '#333' } = point;
    const canvasPoint = transformPoint({ x, y });

    ctx.fillStyle = color;
    ctx.font = `${Math.max(8, 10 * scaleFactor)}px Arial`; // Reduced from 12 to 10
    ctx.textAlign = 'left';

    const offsetX = 10 * scaleFactor;
    const offsetY = 5 * scaleFactor;

    let labelX = canvasPoint.x + offsetX;
    let labelY = canvasPoint.y - offsetY;

    const labelWidth = 80 * scaleFactor;
    if (labelX > width - labelWidth) { labelX = canvasPoint.x - labelWidth; }
    if (labelY < 60 * scaleFactor) { labelY = canvasPoint.y + 20 * scaleFactor; }
    if (labelY > height - 30 * scaleFactor) { labelY = canvasPoint.y - 10 * scaleFactor; }

    const displayLabel = label || `(${x}, ${y})`;
    ctx.fillText(displayLabel, labelX, labelY);
  };

  const drawHorizontalTrendLabel = (ctx: CanvasRenderingContext2D): void => {
    const scaleFactor = width / 450;
    ctx.fillStyle = '#333';
    ctx.font = `bold ${Math.max(8, 12 * scaleFactor)}px Microsoft YaHei`;
    ctx.textAlign = 'left';
    const labelY = Math.max(25, 40 * scaleFactor);
    const padding = 10 * scaleFactor;
    ctx.fillText(`水平趋势 ${horizontalTrend} mm/m`, padding, labelY);
  };

  const transformPoint = (point: { x: number; y: number }): CanvasPoint => {
    return {
      x: centerX + point.x * scale,
      y: centerY - point.y * scale
    };
  };

  return (
    <div
      ref={containerRef}
      style={{
        display: 'flex',
        justifyContent: 'center',
        alignItems: 'center',
        width: '100%',
        height: '100%',
        minWidth: '150px',
        minHeight: '112px',
        boxSizing: 'border-box'
      }}
    >
      <canvas
        ref={canvasRef}
        style={{
          background: 'transparent',
          display: 'block',
          maxWidth: '100%',
          maxHeight: '100%'
        }}
      />
    </div>
  );
};

// 示例使用组件
const App: React.FC = () => {
  const chartData = {
    horizontalTrend: -1.48,
    points: [
      { x: 5, y: 3, color: '#2196F3', label: '(5, 3)' },
      { x: 3, y: 32, color: '#2196F3', label: '(3, 32)' },
      { x: 5, y: -10, color: '#FF5722', label: '(5, -10)' },
      { x: 32, y: -10, color: '#FF5722', label: '(32, -10)' }
    ] as Point[],
    lines: [
      {
        points: [{ x: 5, y: 3 }, { x: 3, y: 32 }],
        color: '#2196F3',
        width: 4
      },
      {
        points: [{ x: 5, y: -10 }, { x: 32, y: -10 }],
        color: '#FF5722',
        width: 4
      }
    ] as Line[]
  };

  return (
      <CoordinateChart
        points={chartData.points}
        lines={chartData.lines}
        horizontalTrend={chartData.horizontalTrend}
        scale={1}
        autoResize={true}
        aspectRatio={4/3}
      />
  );
};

export default App;